#include <avr/io.h>
#include <string.h> 
#include <ctype.h>

#include "BuffFifo.h"
#include "serial.h"
#include "uart.h"

#define TIME_SERIAL_INTERVAL 10 //10ms
unsigned int time_serial; 
unsigned int time_serial_task;

#define SERIAL_CMD_BUFF 20
struct 
{
	unsigned char size; 
	char buff[SERIAL_CMD_BUFF+1];
}sSerialCommand;


void InitSerial( void )
{
	//InitUART(BAUD(115200));
	InitUART(BAUD(19200));
	time_serial = TIME_SERIAL_INTERVAL;
	time_serial_task = 10; //TIME_SERIAL_INTERVAL * 10 = 100ms
	
	memset((void *)&sSerialCommand,0,sizeof(sSerialCommand));
}

void TimeSerial( void )
{
	if(time_serial > 0)
	{
		time_serial--;
		if(time_serial==0)
		{
			if(time_serial_task>0)
			{
				time_serial_task--;
			}
			time_serial = TIME_SERIAL_INTERVAL;
		}
	}
}


void SerialMail(unsigned char act, unsigned char size, char * pbuf)
{
	char c;
	unsigned char loop;
	
	if(act == 0x01)
	{
		for(loop=0;loop<size;loop++)
		{			
			c = BuffPullFifo((psBufFifo)pbuf);
			if( c != FIFO_ERR)
			{
				putchar( c );
			}
		}
	}
}

int doStringCompare(char * pS1,char * pS2,char cLeng)
{
	do
	{	
		if( (*pS1 != ' ') || (*pS2 == ' ') )
		{			
			if( tolower(*pS1++) != tolower(*pS2++) )
			{
				return FALSE;
			} 
			
			if (*pS2 == '\0')
			{
				if( (*pS1 == ' ') || (*pS1 == '\0') )
					return TRUE;
				else
					return FALSE;
			}
			
			cLeng--;
		}
		else
			pS1++;			
	}
	while(cLeng != 0);
	
	return TRUE;
}

int IsStrNumber(char cStr)
{
	if( cStr >= '0' && cStr <= '9' )
	{
		return TRUE;
	}
	return FALSE;
}

int IsTimeNumer(char *pTime)
{
	unsigned char ucH = (*(pTime + 0)*10) + *(pTime + 1);	
	unsigned char ucM = (*(pTime + 2) *10)  + *(pTime + 3);	

	if( (ucH < 24) && (ucM < 60) )
		return TRUE;
	else
		return FALSE;	
}

int IsTimeformat(char *pStr, char *pTime)
{
	unsigned char ucGetStrCount = 0;
	unsigned char ucStrCount = 0;
	int 		  iRunning = TRUE;
	int           iStatus = FALSE;
	
	do
	{
		if( *pStr != ' ' )
		{
			switch( ucStrCount )
			{
				case 0:
				case 1:
				case 3:
				case 4:
					if( IsStrNumber(*pStr) == TRUE )
					{
						*(pTime + ucGetStrCount) = *pStr - '0';
						ucGetStrCount++;
					}					
					else
					{
						iRunning = FALSE;
					}
					break;
				case 2:
					if( *pStr != ':' )
					{
						iRunning = FALSE;
					}					
					break;
				default:
					if( ucGetStrCount == 4 && ( *pStr == '\0' || *pStr == ' ') )
					{
						iStatus  = TRUE;
					}					
					iRunning = FALSE;					
					break;					
			}
			ucStrCount++;			
		}
		pStr++;
	}
	while(iRunning == TRUE);
			
	return iStatus;
}

void sendMainMessage(char cAct, char * pPtr)
{

}


void doOutputError( char cErrCode )
{

}

const char str_act[] 		= "act";
const char str_time[] 		= "time";
const char str_toggle[] 	= "toggle";
const char str_all[] 		= "all";
const char str_on[] 		= "on";
const char str_off[] 		= "off";
const char str_disable[] 	= "disable";

static char cDataBuf[4] = {0,0,0,0};
void doSerialCommand(char * pCmd)
{
	char * pcPost;

	if( doStringCompare(pCmd, (char*)&str_act, sizeof(str_act)) == TRUE )
	{
		pcPost = pCmd + strlen(str_act); 
		if( *pcPost == ' ' )
		{
			pcPost++;
			if( IsStrNumber(*pcPost) == TRUE )
			{
				if( IsStrNumber(*(pcPost+1)) == TRUE )
				{
					sendMainMessage(((*pcPost - '0')*10) + (*(pcPost+1) - '0'),NULL);
				}
				else
					sendMainMessage(*pcPost - '0',NULL);
			}
			else
				doOutputError(3);
		}
		else
			doOutputError(4);	
	}
	else if( doStringCompare(pCmd, (char*)&str_time, sizeof(str_time)) == TRUE )
	{
		pcPost = pCmd + strlen(str_time); 
		if( doStringCompare(pcPost, (char*)&str_all, strlen(str_all)) == TRUE )		
			sendMainMessage(10,NULL);
		else if( doStringCompare(pcPost, (char*)&str_on, strlen(str_on)) == TRUE )		
		{
			pcPost = pCmd + strlen(str_time) + strlen(" ") + strlen(str_on); 
			if( doStringCompare(pcPost, (char*)&str_disable, strlen(str_disable)) == TRUE )					
				sendMainMessage(17,NULL);					
			else if( IsTimeformat(pcPost,(char *)&cDataBuf) == TRUE )
			{
				if( IsTimeNumer((char *)&cDataBuf) == TRUE )
					sendMainMessage(15,(char *)&cDataBuf);
				else
					doOutputError(1);					
			}
			else
				sendMainMessage(12,NULL);							
		}
		else if( doStringCompare(pcPost, (char*)&str_off, strlen(str_off)) == TRUE )		
		{
			pcPost = pCmd + strlen(str_time) + strlen(" ") + strlen(str_off); 
			if( doStringCompare(pcPost, (char*)&str_disable, strlen(str_disable)) == TRUE )					
				sendMainMessage(17,NULL);								
			else if( IsTimeformat(pcPost,(char *)&cDataBuf) == TRUE )
			{
				if( IsTimeNumer((char *)&cDataBuf) == TRUE )
					sendMainMessage(16,(char *)&cDataBuf);
				else
					doOutputError(1);							
			}
			else
				sendMainMessage(13,NULL);
		}
		else if( *pcPost == ' ' )
		{
			if( IsTimeformat(pcPost,(char *)&cDataBuf) == TRUE )
			{
				if( IsTimeNumer((char *)&cDataBuf) == TRUE )
					sendMainMessage(14,(char *)&cDataBuf);
				else
					doOutputError(1);					
			}
			else
			{
				pcPost++;
				if( *pcPost == '+' )
				{
					pcPost++;
					if( IsStrNumber(*pcPost) == TRUE && *pcPost < '4')
					{
						sendMainMessage(20 + *pcPost - '0',NULL);
					}
					else					
						doOutputError(2);					
				}
				else if( *pcPost == '-' )
				{
					pcPost++;
					if( IsStrNumber(*pcPost) == TRUE && *pcPost < '4')
					{
						sendMainMessage(25 + *pcPost - '0',NULL);
					}									
					else					
						doOutputError(2);							
				}
				else
					sendMainMessage(11,NULL);
			}
		}
		else if( *pcPost == '\0' )		
			sendMainMessage(11,NULL);
		else
			doOutputError(0);			
	}
	else if( doStringCompare(pCmd, (char*)&str_toggle, strlen(str_toggle)) == TRUE )
	{		
		pcPost = pCmd + strlen(str_toggle);
		if( doStringCompare(pcPost, "0", strlen("0")) == TRUE )		
			sendMainMessage(90,NULL);
		else if( doStringCompare(pcPost, "1", strlen("1")) == TRUE )		
			sendMainMessage(91,NULL);
		else if( doStringCompare(pcPost, "2", strlen("2")) == TRUE )		
			sendMainMessage(92,NULL);
		else if( doStringCompare(pcPost, "3", strlen("3")) == TRUE )		
			sendMainMessage(93,NULL);
		else if( doStringCompare(pcPost, "4", strlen("4")) == TRUE )		
			sendMainMessage(94,NULL);
		else if( doStringCompare(pcPost, (char*)&str_off, strlen(str_off)) == TRUE )		
			sendMainMessage(95,NULL);
		else if( doStringCompare(pcPost, (char*)&str_all, strlen(str_all)) == TRUE )
			sendMainMessage(96,NULL);
		else
			doOutputError(0);
	}
	else
		doOutputError(0);
	
}


void SerialTask( void )
{
	char c;
	
	if(time_serial_task==0)
	{
		time_serial_task = 20; //TIME_SERIAL_INTERVAL * 20 = 200ms
		if(isRxNotEmpty() == TRUE)
		{
			time_serial_task = 5; //TIME_SERIAL_INTERVAL * 5 = 50ms
			if ((c = getchar()) >= 0)
			{
				if(c=='\r')
				{
					printf("\r\n");
					sSerialCommand.buff[sSerialCommand.size] = '\0';
					doSerialCommand((char *)&sSerialCommand.buff);
					sSerialCommand.size = 0;
				}
				else										
				{
					putchar(c);
					if(sSerialCommand.size < SERIAL_CMD_BUFF)
					{
						sSerialCommand.buff[sSerialCommand.size] = c;
						sSerialCommand.size++;						
					}
					else
					{
						sSerialCommand.buff[sSerialCommand.size] = '\0';
						doSerialCommand((char *)&sSerialCommand.buff);
						sSerialCommand.size = 0;
					}
				}
			}
		}
	}	
	

}
